function printLabel(labelledObj: { label: string }) {
  console.log(labelledObj.label)
}

// let myObj = { size: 10, label: 12 };     // error
let myObj = { size: 10, label: 'Size 10 Object' }
printLabel(myObj)

// 类型检查器会查看printLabel的调用。 printLabel有一个参数，并要求这个对象参数有一个名为label类型
// 为string的属性。 需要注意的是，我们传入的对象参数实际上会包含很多属性，但是编译器只会检查那些必需的属性
// 是否存在，并且其类型是否匹配。

;(function () {
  interface LabelledValue {
    label: string
  }

  function printLabel(labelledObj: LabelledValue) {
    console.log(labelledObj.label)
  }

  let myObj = { size: 10, label: 'Size 10 Object' }
  printLabel(myObj)
})()

{
  // 可选属性  带有可选属性的接口与普通的接口定义差不多，只是在可选属性名字定义的后面加一个?符号。
  interface SquareConfig {
    color?: string
    width?: number
  }

  function createSquare(config: SquareConfig): { color: string; area: number } {
    let newSquare = { color: 'white', area: 100 }
    if (config.color) {
      newSquare.color = config.color
    }
    if (config.width) {
      newSquare.area = config.width * config.width
    }
    return newSquare
  }

  let mySquare = createSquare({ color: 'black' })
}

{
  // 只读属性  一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用readonly来指定只读属性:
  interface Point {
    readonly x: number
    readonly y: number
  }

  let p1: Point = { x: 10, y: 20 }
  //   p1.x = 5; // error!

  //   TypeScript具有ReadonlyArray<T>类型，它与Array<T>相似，只是把所有可变方法去掉了，因此可以确保数组创建后再也不能被修改：
  let a: number[] = [1, 2, 3, 4]
  let ro: ReadonlyArray<number> = a
  //   ro[0] = 12; // error!
  //   ro.push(5); // error!

  //   函数类型
  //   接口能够描述JavaScript中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外，接口也可以描述函数类型。
  interface SearchFunc {
    (source: string, subString: string): boolean
  }
  let mySearch: SearchFunc
  mySearch = function (source: string, subString: string) {
    let result = source.search(subString)
    return result > -1
  }
  // 或者使用下面的方式
  let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
    return x + y
  }

  function sum(x: number, y: number): number {
    return x + y
  }

  // 函数重载
  function reverse(x: number): number
  function reverse(x: string): string
  function reverse(x: number | string): number | string | void {
    if (typeof x === 'number') {
      return Number(x.toString().split('').reverse().join(''))
    } else if (typeof x === 'string') {
      return x.split('').reverse().join('')
    }
  }
  // 我们重复定义了多次函数 reverse，前几次都是函数定义，最后一次是函数实现。在编辑器的代码提示中，可以正确的看到前两个提示。

  // 类型断言  书写方式:  值 as 类型 或者 <类型>值

  //   类实现接口
  interface ClockInterface {
    currentTime: Date
    setTime(d: Date): void
  }

  class Clock implements ClockInterface {
    currentTime: Date
    setTime(d: Date) {
      this.currentTime = d
    }
    constructor(h: number, m: number) {}
  }
  console.log(new Clock(1, 2))

  //   继承接口
  interface Shape {
    color: string
  }

  interface Square extends Shape {
    sideLength: number
  }

  //   let square = <Square>{};
  //   square.color = "blue";
  //   square.sideLength = 10;
}
